/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.core.converter;

import vip.dexian.common.utils.JsonUtils;
import com.fasterxml.jackson.databind.JavaType;
import jakarta.persistence.AttributeConverter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.ResolvableType;

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 属性转换器，用于数据库字段内容转换为对象，将对象转换为json
 *
 * @param <T>
 *
 * @author 挺好的 2023年06月01日 17:24
 */
public abstract class BaseAttributeConverter<T> implements AttributeConverter <T, String> {

    /**
     * java
     */
    private final JavaType javaType;

    public BaseAttributeConverter () {
        ResolvableType resolvableType = ResolvableType.forClass(this.getClass());
        Type type = resolvableType.getSuperType().getGeneric().getType();
        this.javaType = JsonUtils.constructType(type);
    }

    /**
     * 转换为数据库的某个字段。
     *
     * @param attribute
     *         待转换的属性
     *
     * @return json数据
     *
     * @see JsonUtils
     */
    @Override
    public String convertToDatabaseColumn (Object attribute) {
        if (attribute == null) {
            return null;
        }

        return JsonUtils.toJson(attribute);
    }

    /**
     * 转换为实体的属性
     *
     * @param dbData
     *         数据库中的数据
     *
     * @return 数据对象
     */
    @Override
    public T convertToEntityAttribute (String dbData) {
        if (StringUtils.isEmpty(dbData)) {
            if (List.class.isAssignableFrom(this.javaType.getRawClass())) {
                return (T) Collections.emptyList();
            } else if (Set.class.isAssignableFrom(this.javaType.getRawClass())) {
                return (T) Collections.emptySet();
            } else if (Map.class.isAssignableFrom(this.javaType.getRawClass())) {
                return (T) Collections.emptyMap();
            } else {
                return null;
            }
        }
        return JsonUtils.toObject(dbData, this.javaType);
    }

}
